package buildinjava.cpp;

import buildinjava.BuildException;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Compiles source-code using the Microsoft Studio compiler.
 * 
 * @author Gili Tzabari
 */
public final class VisualStudio
{
	/**
	 * Sets the solution file.
	 *
	 * @param solution the solution file
	 * @return a HaveSolution instance
	 */
	public HaveSolution solution(File solution)
	{
		return new HaveSolution(solution);
	}

	/**
	 * Configured with a build solution.
	 *
	 * @author Gili Tzabari
	 */
	public static final class HaveSolution
	{
		private final File solution;

		/**
		 * Creates a new HaveSolution object.
		 * 
		 * @param solution the solution file
		 */
		public HaveSolution(File solution)
		{
			this.solution = solution;
		}

		/**
		 * Sets the build configuration.
		 *
		 * @param configuration the build configuration
		 * @return the VisualStudio
		 */
		public HaveConfiguration configuration(String configuration)
		{
			return new HaveConfiguration(solution, configuration);
		}
	}

	/**
	 * Configured with a build solution and configuration.
	 *
	 * @author Gili Tzabari
	 */
	public static final class HaveConfiguration
	{
		private final File solution;
		private final String configuration;

		/**
		 * Creates a new HaveConfiguration object.
		 *
		 * @param solution the solution file
		 * @param configuration the build configuration
		 */
		public HaveConfiguration(File solution, String configuration)
		{
			this.solution = solution;
			this.configuration = configuration;
		}

		/**
		 * Sets the build platform.
		 *
		 * @param platform the build platform
		 * @return an instance of Builder
		 */
		public Builder platform(String platform)
		{
			return new Builder(solution, configuration, platform);
		}
	}

	/**
	 * Builds a solution.
	 *
	 * @author Gili Tzabari
	 */
	public static final class Builder
	{
		private final File solution;
		private final String configuration;
		private final String platform;

		/**
		 * Creates a new Builder.
		 *
		 * @param solution the solution file
		 * @param configuration the build configuration
		 * @param platform the build platform
		 */
		public Builder(File solution, String configuration, String platform)
		{
			this.solution = solution;
			this.configuration = configuration;
			this.platform = platform;
		}

		/**
		 * Builds the solution.
		 */
		public void build()
		{
			String visualStudioPath = System.getenv("VS90COMNTOOLS");
			if (visualStudioPath == null)
				throw new BuildException("%VS90COMNTOOLS% does not exist");
			File compiler = new File(visualStudioPath + "..\\IDE\\devenv.com");
			if (!compiler.exists())
				throw new BuildException(compiler.getAbsolutePath() + " does not exist");
			ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c",
				compiler.getPath(), solution.getName(), "/build", configuration + "^|" + platform);

			builder.directory(solution.getParentFile());
			builder.redirectErrorStream(true);
			try
			{
				Process process = builder.start();
				BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
				try
				{
					while (true)
					{
						String line = in.readLine();
						if (line == null)
							break;
						System.out.println(line);
					}
					if (process.exitValue() != 0)
						throw new BuildException("Return code: " + process.exitValue());
				}
				finally
				{
					in.close();
				}
			}
			catch (IOException e)
			{
				throw new BuildException(e);
			}
		}
	}
}
